![]() Acrobat file (195K) |
![]() ClarisWorks 4 file (42K) |
![]() QuickView file (284K) |
Technote 1013 | FEBRUARY 1996 |
Apple's PC Compatibility systems present an interesting dilemma when trying to print from the DOS/Windows side of the CPU because all of the I/O of this system must occur through the Macintosh. DOS applications and Windows printer drivers generate native printer codes for specific printers, but do not generate the QuickDraw commands that Macintosh printer drivers depend on in order to image data to a specific printer. This printer direct mode will allow a "back-door" for these native printer commands to get directly to the printer through the Macintosh printer driver.
This Technote is directed towards printer driver developers who write drivers for non-PostScript printers. Implementing this feature will allow faster and better quality printing with Apple's PC Compatibility products, where printing must always occur on the Macintosh, even though the printer driver generating the printer commands may be on a DOS/Windows system.
This document assumes you are familiar with the Macintosh Printing Manager and Apple's
PC Compatibility products. See Inside Macintosh:Imaging with QuickDraw
for further details on the Printing Manager.
Contents
#define kPrinterDirectOpCode 20 #define kPDOpenSelect 1 #define kPDSendDataSelect 2 #define kPDSendFileSelect 3 #define kPDCloseSelect 4 #define kPDDespoolSelect 5 #define kPDVerifySelect 6If the driver does not support the printer direct opCode, the PrGeneral function should return a opNotImpl error. This is the one case where an error code will only be returned in the printer error (PrError). For all the rest of the functions, error codes need to be returned in the error field of the parameter block as well as the printing error variable (PrSetError).
#define kPDData 1 #define kPDFileSpec 2If any other value is set in the spoolType field, the function should return the pdBadSpoolTypeErr. The format of the parameter block is:
struct OpenPDBlk { SInt16 opCode; // Printer Direct opCode = 20 OSErr error; // Result code UInt32 reserved; // reserved UInt32 selector; // Function selector code UInt32 jobID; // ID referencing this job UInt32 spoolType; // Ptr to data or FSSpec. }; typedef struct OpenPDBlk OpenPDBlk, *OpenPDBlkPtr;
struct SendPDDataBlk { SInt16 opCode; // Printer Direct opCode = 20 OSErr error; // Result code UInt32 reserved; // reserved UInt32 selector; // Function selector code UInt32 jobID; // ID referencing this job Ptr Data; // Pointer to the data. UInt32 count; // Number of bytes Data points to. }; typedef struct SendPDDataBlk SendPDDataBlk, *SendPDDataBlkPtr;
struct SendPDFileSpecBlk { SInt16 opCode; // Printer Direct opCode = 20 OSErr error; // Result code UInt32 reserved; // reserved UInt32 selector; // Function selector code UInt32 jobID; // ID referencing this job FSSpec fileSpec; // Points to file where data is }; typedef struct SendPDFileSpecBlk SendPDFileSpecBlk, *SendPDFileSpecBlkPtr;
struct ClosePDBlk { SInt16 opCode; // Printer Direct opCode = 20 OSErr error; // Result code UInt32 reserved; // reserved UInt32 selector; // Function selector code UInt32 jobID; // ID referencing this job }; typedef struct ClosePDBlk ClosePDBlk, *ClosePDBlkPtr;
struct DespoolPDBlk { SInt16 opCode; // Printer Direct opCode = 20 OSErr error; // Result code UInt32 reserved; // reserved UInt32 selector; // Function selector code UInt32 jobID; // ID referencing this job UniversalProcPtr idleProcPtr; // idleProc }; typedef struct DespoolPDBlk DespoolPDBlk, *DespoolPDBlkPtr;
pascal void MyIdleProc(void);The primary purpose of the idleProc is to sense events when a user is attempting to abort the print job. Should the idleProc sense this, it must set the printing error (via the PrSetError function) with the iPrAbort error. Otherwise, the idleProc should return a noErr. The driver should check the error returned and abort the print job upon receiving the abort error.
Should the despool procedure be aborted, it should return the iPrAbort error. If the despool function should fail for any other reason, it should return the pdDespoolFailedErr so the calling application can prompt the user.
If the idleProc is nil, it is the printer driver's option to supply a default idleProc routine.
struct VerifyPDBlk { SInt16 opCode; // Printer Direct opCode = 20 OSErr error; // Result code UInt32 reserved; // reserved UInt32 selector; // Function selector code OSType drvrCreator; // Printer driver's creator type NumVersion drvrVersion; // Printer driver's version number }; typedef struct VerifyPDBlk VerifyPDBlk, *VerifyPDBlkPtr;The drvrCreator and drvrVersion fields are returned by the printer driver. The drvrCreator is a 4 character OSType that is part of the driver's file info. The drvrVersion field is of type NumVersion which is defined in the Types.h file of the Macintosh headers. It is defined there as follows:
struct NumVersion { UInt8 majorRev; /*1st part of version number in BCD*/ UInt8 minorAndBugRev; /*2nd & 3rd part of version number share a byte*/ UInt8 stage; /*stage code:dev, alpha, beta, final*/ UInt8 nonRelRev; /*revision level of non-released version*/ }; typedef struct NumVersion NumVersion;Based on the creator and version information, and any pertinent information in the printer record, it is up to the calling application to determine whether the printer data being sent to this driver would be handled properly by this printer.
#define kPrinterDirectOpCode 20 #define kPDOpenSelect 1 #define kPDSendDataSelect 2 #define kPDSendFileSelect 3 #define kPDCloseSelect 4 #define kPDDespoolSelect 5 #define kPDVerifySelect 6 #define kPDNoData 0 #define kPDData 1 #define kPDFileSpec 2 enum { pdBadSelectorErr = -10001, pdBadSendModeErr = -10002, pdBadJobIDErr = -10003, pdDespoolFailed = -10004 };
struct OpenPDBlk { SInt16 opCode; // Printer Direct opCode = 20 OSErr error; // Result code UInt32 reserved; // reserved UInt32 selector; // Function selector code UInt32 jobID; // ID referencing this job UInt32 spoolType; // Ptr to data or FSSpec. }; typedef struct OpenPDBlk OpenPDBlk, *OpenPDBlkPtr; struct SendPDDataBlk { SInt16 opCode; // Printer Direct opCode = 20 OSErr error; // Result code UInt32 reserved; // reserved UInt32 selector; // Function selector code UInt32 jobID; // ID referencing this job Ptr Data; // Pointer to the data. UInt32 count; // Number of bytes Data points to. }; typedef struct SendPDDataBlk SendPDDataBlk, *SendPDDataBlkPtr; struct SendPDFileSpecBlk { SInt16 opCode; // Printer Direct opCode = 20 OSErr error; // Result code UInt32 reserved; // reserved UInt32 selector; // Function selector code UInt32 jobID; // ID referencing this job FSSpec fileSpec; // Points to file where data is }; typedef struct SendPDFileSpecBlk SendPDFileSpecBlk, *SendPDFileSpecBlkPtr; struct ClosePDBlk { SInt16 opCode; // Printer Direct opCode = 20 OSErr error; // Result code UInt32 reserved; // reserved UInt32 selector; // Function selector code UInt32 jobID; // ID referencing this job }; typedef struct ClosePDBlk ClosePDBlk, *ClosePDBlkPtr; struct DespoolPDBlk { SInt16 opCode; // Printer Direct opCode = 20 OSErr error; // Result code UInt32 reserved; // reserved UInt32 selector; // Function selector code UInt32 jobID; // ID referencing this job UniversalProcPtr idleProcPtr; // idleProc }; typedef struct DespoolPDBlk DespoolPDBlk, *DespoolPDBlkPtr; struct VerifyPDBlk { SInt16 opCode; // Printer Direct opCode = 20 OSErr error; // Result code UInt32 reserved; // reserved UInt32 selector; // Function selector code OSType drvrCreator; // Printer driver's creator type NumVersion drvrVersion; // Printer driver's version number }; typedef struct VerifyPDBlk VerifyPDBlk, *VerifyPDBlkPtr;
The printer-direct mode will be implemented in PowerPrint 3.0.1 Classic and LT driver packages from GDT Softworks in February, 1996. This feature is also being considered in a future release of Apple's LaserWriter 8 driver. In addition, other third-party providers have shown interest in implementing this feature in their printer drivers in the future.
A caveat: Application developers should realize that this feature is currently not
supported by Apple's drivers.
Acknowledgements
Thanks to Ingrid Kelly, Guillermo Ortiz, and Dave Polaschek for reviewing this Technote.
Special thanks to Tom Dowdy for reviewing the design and helping us think about the
future compatibility. We would also like to thank Greg Manning, Gord Pawluik, Pierre Houston, and Dave Banks from GDT Softworks for their help in reviewing and contributing
to this Technote.